//
//  Optional+Extension.swift
//  RESwiftBaseProject
//
//  Created by Chanjinger on 2018/12/4.
//  Copyright © 2018年 leapp. All rights reserved.
//

import Foundation

extension Optional {
    
    //MARK: - 判空
    ///可选值为空时，返回true
    var isNone: Bool {
        switch self {
        case .none:
            return true
        case .some:
            return false
        }
    }
    
    /// 可选值非空返回 true
    var isSome: Bool {
        return !isNone
    }
    
    //MARK: - Or
    
    ///返回可选值或者默认值
    /// - 参数: 如果可选值为空，返回默认值
    func or(_ default: Wrapped) -> Wrapped {
        return self ?? `default`
    }
    
    ///返回可选值或者 `else`表达式返回的值
    ///例：optional.or(else: print("Arr"))
    func or(else: @autoclosure () -> Wrapped) -> Wrapped {
        return self ?? `else`()
    }
    
    ///返回可选值或者`else`闭包返回的值
    // 例: optional.or(else: {
    /// ... do a lot of stuff
    /// })
    func or(else: () -> Wrapped) -> Wrapped {
        return self ?? `else`()
    }
    
    ///当可选值不为空时，返回可选值
    ///如果为空，抛出异常
    func or(throw exception: Error) throws -> Wrapped {
        guard let unwrapped = self else { throw exception }
        return unwrapped
    }
    
    //MARK: - 变换（Map）
    
    ///可选值变换返回，如果可选值为空，则返回默认值
    /// - 参数 fn: 映射值的闭包
    /// - 参数 default: 可选值为空时将作为返回值
    func map<T>(_ fn: (Wrapped) throws -> T, default: T) rethrows -> T {
        return try map(fn) ?? `default`
    }
    
    ///可选值b变换返回，如果可选值为空，则调用 `else`闭包
    /// - 参数 fn: 映射值的闭包
    /// - 参数 else: 可选值为空时调用
    func map<T>(_ fn: (Wrapped) throws -> T, else: () throws -> T) throws -> T {
        return try map(fn) ?? `else`()
    }
    
    //MARK: - On
    /// 当可选值不为空时，执行 `some` 闭包
    func on(some: () throws -> Void) rethrows {
        if self != nil { try some() }
    }
    
    /// 当可选值为空时，执行 `none` 闭包
    func on(none: () throws -> Void) rethrows {
        if self == nil { try none() }
    }
    
    /// 可选值不为空且可选值满足 `predicate` 条件才返回，否则返回 `nil`
    func filter(_ predicate: (Wrapped) -> Bool) -> Wrapped? {
        guard let unwrapped = self,
            predicate(unwrapped) else { return nil }
        return self
    }
    
    /// 可选值不为空时返回，否则 crash
    func expect(_ message: String) -> Wrapped {
        guard let value = self else { fatalError(message) }
        return value
    }
}

extension Optional where Wrapped == Error {
    ///当可选值不为空时，执行 `else`
    func or(_ else: (Error) -> Void ){
        guard let error = self else { return }
        `else`(error)
    }
}

//MARK: - 组合可选项（Combining Optionals）
extension Optional {
    
    ///当可选值不为空时j，解包并返回参数`optional`
    ///若一个可选值的解包仅作为另一可选值解包的前提
    func add<B>(_ optional: B?) -> B? {
        guard self != nil else { return nil }
        return optional
    }
    
    ///解包可选值，当可选值不为空时，执行`then`闭包，并返回执行结果
    ///允许将多个可选项连接在一起
    func add<T>(then: (Wrapped) throws -> T?) rethrows -> T? {
        guard let unwrapped = self else { return nil }
        return try then(unwrapped)
    }
    
    /// 将当前可选值与其他可选值组合在一起
    /// 当且仅当两个可选值都不为空时组合成功，否则返回空
    func zip2<A>(with other: Optional<A>) -> (Wrapped, A)? {
        guard let first = self, let second = other else { return nil }
        return (first, second)
    }
    
    /// 将当前可选值与其他可选值组合在一起
    /// 当且仅当三个可选值都不为空时组合成功，否则返回空
    func zip3<A, B>(with other: Optional<A>, another: Optional<B>) -> (Wrapped, A, B)? {
        guard let first = self,
            let second = other,
            let third = another else { return nil }
        return (first, second, third)
    }
}



/**

 ///默认闭包（Default Closure--------------------
 let cachedUserCount: Int? = nil
 ...
 return cachedUserCount.or(else: {
 let db = database()
 db.prefetch()
 guard db.failures.isEmpty else { return 0 }
 return db.amountOfUsers
 })
 
 ///抛出异常（Throw an error）--------------------
 func build_car() throws -> Car {
 let tires = try machine1.createTires()
 let windows = try machine2.createWindows()
 let motor = try externalMachine.deliverMotor().or(throw: MachineError.motor)
 let trunk = try machine3.createTrunk()
 return try manufacturer.buildCar(tires, windows,  motor, trunk).or(throw: MachineError.manufacturer)
 }
 
 //错误处理（Handling Errors）--------------------
 func should(_ do: () throws -> Void) -> Error? {
 do {
 try `do`()
 return nil
 } catch let error {
 return error
 }
 }
 
 should { try throwingFunction) }.or(print($0))
 
 
 //变换（Map）--------------------
 let optional1: String? = "appventure"
 // 使用前
 print(optional1.map({ $0.count }) ?? 0)
 // 使用后
 print(optional1.map({ $0.count }, default: 0)) // prints 10
 
 //依赖------------------------
 // 使用前
 let childrenCount: Int
 if let user = database.current(),
 let father1 = database.father(user),
 let father2 = database.father(father1),
 let spouse = database.spouse(father2),
 let children = database.childrenCount(father2) {
 childrenCount = children
 } else {
 childrenCount = 0
 }
 
 // 使用后
 let children = database.current().and(then: { database.spouse($0) })
 .and(then: { database.father($0) })
 .and(then: { database.spouse($0) })
 .and(then: { database.childrenCount($0) })
 .or(0)

 
 作者：SwiftGG翻译组
 链接：https://juejin.im/post/5bf2627ee51d45686a68a245
 来源：掘金
 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
 
*/
